package gamecomponents.sound;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

/**
 * A soundclip.
 * @author Team Deer
 * 
 */
public class SoundClip implements Runnable {

	private static final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb

	private final File file;

	private boolean isRunning = false;

	// Constructor
	
	public SoundClip(String filename) throws UnsupportedAudioFileException,
			IOException, LineUnavailableException {
		if (!filename.startsWith("Content\\Waves\\")) {
			filename = "Content\\Waves\\" + filename + ".wav";
		}
		this.file = new File(filename);
	}

	// Methods
	
	/**
	 * @return Returns whether the sound is playing or not.
	 */
	public boolean isRunning() {
		return this.isRunning;
	}

	@Override
	public void run() {
		this.isRunning = true;
		this.play();
	}
	
	/**
	 * Play this soundclip.
	 */
	public synchronized void play() {

		/*
		 * if (audioLine.isControlSupported(FloatControl.Type.PAN)) {
		 * 
		 * FloatControl pan = (FloatControl) audioLine
		 * .getControl(FloatControl.Type.PAN); if (Right pan)
		 * pan.setValue(1.0f); else if (Left pan) pan.setValue(-1.0f);
		 * 
		 * }
		 */
		AudioInputStream audioInputStream = null;
		try {
			audioInputStream = AudioSystem.getAudioInputStream(this.file);
		} catch (final IOException e1) {
			return;
		} catch (final UnsupportedAudioFileException e) {
			return;
		}

		SourceDataLine audioLine = null;
		try {
			audioLine = (SourceDataLine) AudioSystem.getLine(new DataLine.Info(
					SourceDataLine.class, audioInputStream.getFormat()));
		} catch (final LineUnavailableException e) {
			return;
		}

		try {
			audioLine.open(audioInputStream.getFormat());
		} catch (final LineUnavailableException e) {
			return;
		}

		audioLine.start();
		int nBytesRead = 0;
		final byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];

		while (nBytesRead != -1) {
			try {
				nBytesRead = audioInputStream.read(abData, 0, abData.length);
			} catch (final IOException e) {
				// Fail to read, don't play sound.
				audioLine.close();
				return;
			}
			if (nBytesRead >= 0) {
				audioLine.write(abData, 0, nBytesRead);
			}
		}
		audioLine.drain();
		audioLine.close();
		this.isRunning = false;
	}
}
